//
//  String+SHA1.swift
//  TODOApp
//
//  Created by chenyh on 2018/5/30.
//  Copyright © 2018年 chenyh. All rights reserved.
//

import Foundation
enum CryptoAlgorithm {
    
    /// 加密的枚举选项
    
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512

    var HMACAlgorithm: CCHmacAlgorithm {
        
        var result: Int = 0
        
        switch self {
            
        case .MD5:      result = kCCHmacAlgMD5
            
        case .SHA1:     result = kCCHmacAlgSHA1
            
        case .SHA224:   result = kCCHmacAlgSHA224
            
        case .SHA256:   result = kCCHmacAlgSHA256
            
        case .SHA384:   result = kCCHmacAlgSHA384
            
        case .SHA512:   result = kCCHmacAlgSHA512
            
        }
        
        return CCHmacAlgorithm(result)
        
    }
    
    
    
    var digestLength: Int {
        
        var result: Int32 = 0
        
        switch self {
            
        case .MD5:      result = CC_MD5_DIGEST_LENGTH
            
        case .SHA1:     result = CC_SHA1_DIGEST_LENGTH
            
        case .SHA224:   result = CC_SHA224_DIGEST_LENGTH
            
        case .SHA256:   result = CC_SHA256_DIGEST_LENGTH
            
        case .SHA384:   result = CC_SHA384_DIGEST_LENGTH
            
        case .SHA512:   result = CC_SHA512_DIGEST_LENGTH
            
        }
        
        return Int(result)
        
    }
    
}
extension String {
    
    /*
     
     *   func：加密方法
     
     *   参数1：加密方式； 参数2：加密的key
     
     */

    func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
        
        let str = self.cString(using: String.Encoding.utf8)
        
        let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
        
        let digestLen = algorithm.digestLength
        
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        
        let keyStr = key.cString(using: String.Encoding.utf8)
        
        let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
        
        
    
        CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
        
        
        
        let digest = stringFromResult(result:  result, length: digestLen)
        
        
        
        result.deallocate(capacity: digestLen)
        
        
        
        return digest
        
    }
    
    
    
    private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
        
        let hash = NSMutableString()
        
        for i in 0..<length {
            
            hash.appendFormat("%02x", result[i])
            
        }
        
        return String(hash)
        
    }

    
    //MARK: - MD5
    
    func md5() -> String {
        
        let cStr = self.cString(using: String.Encoding.utf8);
        
        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 16)
        
        CC_MD5(cStr!,(CC_LONG)(strlen(cStr!)), buffer)
        
        let md5String = NSMutableString();
        
        for i in 0 ..< 16{
            
            md5String.appendFormat("%02x", buffer[i])
            
        }
        
        free(buffer)
        
        return md5String as String
        
        
        
    }
    
    //MARK: - sha1 加密
    
    func sha1() -> String {
        
        
        
        let data = self.data(using: String.Encoding.utf8)!
        
        var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
        
        
        
        let newData = NSData.init(data: data)
        
        CC_SHA1(newData.bytes, CC_LONG(data.count), &digest)
        
        let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
        
        for byte in digest {
            
            output.appendFormat("%02x", byte)
            
        }
        
        return output as String
        
    }
    
    
}
